Amazon S3 + CloudFrontによるYumリポジトリにリダイレクトルールを適用する
ども、大瀧です。
ソフトウェア配布の手段として、Amazon CloudFrontは非常に強力です。CDNとして世界各地からのアクセスに対して良好なパフォーマンスが期待できますし、多数の同時アクセス負荷を分散させる効果も期待できます。さらにCloudFrontのオリジン(配信元)としてAmazon S3を利用すると、仮想マシンを実行することなくリーズナブルで可用性の高いソフトウェア配信基盤が構成できます。
ただ、S3はWebサーバーとしての機能は一般的なWebサーバーと比べて少ないため、用意されているオプションを理解しうまく活用することが重要です。そこで今回は、S3 Static Website Hostingのリダイレクトルールを利用してYumリポジトリの少し込み入った構成をご紹介します。
構成の概要
まずは、CloudFrontとS3の構成です。Linuxのソフトウェア配布方法としてよく用いられるYumでは、RPMパッケージを配置するYumリポジトリをパッケージの配布元として用意します。Yumリポジトリ自体はXMLファイルなどの静的コンテンツで動作するため、CloudFront + S3でも問題なく動作します。LinuxホストでYumリポジトリの設定をCloudFrontを向くように行いyumコマンドを実行します。CloudFrontでは初回のみS3にパッケージファイル取得のリクエストを発行、キャッシュしつつLinuxホストにパッケージファイルを返送します。
Yumリポジトリはシンプルなディレクトリごと独立した構成なので、S3バケットの中にディレクトリ(プリフィックス)別の複数Yumリポジトリを配置することもできます。そこで、OSのメジャーバージョン毎にリポジトリを分け、Yumの変数$releaseverを利用してリポジトリの設定内に以下のように記述することがよくあります。
Amazon Linuxの/etc/yum.repos.d/amzn-main.repo
[amzn-main] name=amzn-main-Base mirrorlist=http://repo.$awsregion.$awsdomain/$releasever/main/mirror.list :(以下略)
ただ、リポジトリによってはOSのバージョンに拠らず同じリポジトリを参照させたいこともあると思います。$releaseverを含めない対応が最もシンプルですが、RHELとAmazon Linuxなど複数ディストリビューションで共通のリポジトリの設定にしたいこともあるでしょう。そういう場合は、特定バージョンのリポジトリを他のバージョンのリポジトリから参照させる方法が考えられます。他のリポジトリへの参照は、大きく分けて以下の2通りがあります。
- シンボリックリンク
- HTTPリダイレクト
シンボリックリンクへの追随はWebサーバー側の設定(Apacheの場合はFollowSymlinks)、HTTPリダイレクトはyumコマンドが既定で追ってくれるので特別な対応は要りません。今回リポジトリを構成するS3では、バケット内のファイル(オブジェクト)にシンボリックリンクを設定することはできないため、HTTPリダイレクトを設定することになります。例えば、以下のような構成です。
RHEL向けの/7ディレクトリにリポジトリのファイルを配置し、Amazon Linux向けの/latestや/2015.03などを/7にリダイレクトさせます。
では、順を追って設定していきます。
- 動作確認環境 : Amazon Linux 2015.03 HVM(東京リージョン : ami-cbf90ecb)
RPMパッケージとYumリポジトリの作成
まずはサンプルのRPMパッケージとYumリポジトリをさくっと作っちゃいます。1ファイル/hoge.txtを含むhogeパッケージをfpmコマンドでパッケージングします。
$ sudo yum groupinstall -y "Development Tools" $ sudo yum install -y ruby-devel $ sudo gem install fpm --no-ri --no-rdoc $ mkdir src $ echo "Hoge" > src/hoge.txt $ cat src/hoge.txt Hoge $ fpm -s dir -t rpm -n hogehoge -v 0.0.1 -C src -p pkg/hogehoge-0.0.1.rpm . no value for epoch is set, defaulting to nil {:level=>:warn} no value for epoch is set, defaulting to nil {:level=>:warn} Created package {:path=>"pkg/hogehoge-0.0.1.rpm"} $ rpm -qlp pkg/hogehoge-0.0.1.rpm /hoge.txt $
できたhogeパッケージを配置しているpkg/ディレクトリをYumリポジトリのルートとし、createrepoコマンドでYumリポジトリを作成します。
$ sudo yum install -y createrepo $ createrepo pkg/ Spawning worker 0 with 1 pkgs Workers Finished Saving Primary metadata Saving file lists metadata Saving other metadata Generating sqlite DBs Sqlite DBs complete $ ls pkg/ hogehoge-0.0.1.rpm repodata $
Yumリポジトリのメタデータはrepodata/配下にXMLファイルといくつかのファイルで構成されます。これでYumリポジトリのファイル作成はOKです。
念のためデバッグしてみましょう。Yumリポジトリの設定ファイル(/etc/yum.repos.d/hoge.repo)を作成し、リポジトリのディレクトリを絶対パスで記述します。
/etc/yum.repos.d/hoge.repo
[hoge] baseurl=file:///home/ec2-user/pkg/ enable=yes gogpcheck=no
では、yumコマンドでYumリポジトリが動作するか確認してみます。
$ yum info hoge 読み込んだプラグイン:priorities, update-motd, upgrade-helper リポジトリー 'hoge' は構成中に名前がありませんので ID を使います hoge | 2.9 kB 00:00 hoge/primary_db | 1.6 kB 00:00 利用可能なパッケージ 名前 : hogehoge アーキテクチャー : x86_64 バージョン : 0.0.1 リリース : 1 容量 : 1.8 k リポジトリー : hoge 要約 : no description given URL : http://example.com/no-uri-given ライセンス : unknown 説明 : no description given $
きちんとyumコマンドでパッケージが読めていますね!
S3 Static Website Hostingの設定
YumリポジトリのファイルをS3にアップロードします。あらかじめ任意のS3バケット *1を作成します。リダイレクトを動作させるためにはStatic Website Hosting機能を有効にし、リダイレクトルールを記述します。
- バケットの[Properties]ボタンをクリックし、[Static Website Hosting]のアコーディオンメニューを開く
- [Enable website hosting]のラジオボタンをクリック
- [Index Document]は任意のファイル名を入力(yumコマンドはindex.htmlを読まないので動作には影響なし)
- [Edit Redirection Rules]をクリックし、テキストエリアに以下を入力 *2
<RoutingRules> <RoutingRule> <Condition> <KeyPrefixEquals>latest/</KeyPrefixEquals> </Condition> <Redirect> <ReplaceKeyPrefixWith>7/</ReplaceKeyPrefixWith> </Redirect> </RoutingRule> <RoutingRule> <Condition> <KeyPrefixEquals>2014.09/</KeyPrefixEquals> </Condition> <Redirect> <ReplaceKeyPrefixWith>7/</ReplaceKeyPrefixWith> </Redirect> </RoutingRule> <RoutingRule> <Condition> <KeyPrefixEquals>2015.03/</KeyPrefixEquals> </Condition> <Redirect> <ReplaceKeyPrefixWith>7/</ReplaceKeyPrefixWith> </Redirect> </RoutingRule> </RoutingRules>
入力後は画面下方の[Save]ボタンのクリックを忘れずに!続いて、AWS CLIなどでYumリポジトリのディレクトリ以下のすべてのファイルをアップロードします。awsコマンドを実行するマシンでは、あらかじめS3にアクセスできるようIAMロールもしくはAPIキーの設定を済ませておきます。
$ aws s3 cp --recursive --acl public-read pkg/ s3://takipone-repotest/7/ upload: pkg/repodata/2211fa11fd76daa7aceabf19418bf8294bf51bb8b57e2e1095a6761a3a38c91b-primary.sqlite.bz2 to s3://takipone-repotest/7/repodata/2211fa11fd76daa7aceabf19418bf8294bf51bb8b57e2e1095a6761a3a38c91b-primary.sqlite.bz2 upload: pkg/repodata/61235ed0c793230e12ceb017cea85ae2ba60c058357ef8ae608d779b2aa0e308-other.sqlite.bz2 to s3://takipone-repotest/7/repodata/61235ed0c793230e12ceb017cea85ae2ba60c058357ef8ae608d779b2aa0e308-other.sqlite.bz2 upload: pkg/repodata/704ef5cd32e4ec64f3f7d85b093ef3d0ac64de8674dc38f9af1b428415b07f0e-other.xml.gz to s3://takipone-repotest/7/repodata/704ef5cd32e4ec64f3f7d85b093ef3d0ac64de8674dc38f9af1b428415b07f0e-other.xml.gz upload: pkg/repodata/repomd.xml to s3://takipone-repotest/7/repodata/repomd.xml upload: pkg/repodata/d1f86b89886bda187279e38780d28a20ac3669523e467d1df057a91d7047738c-filelists.sqlite.bz2 to s3://takipone-repotest/7/repodata/d1f86b89886bda187279e38780d28a20ac3669523e467d1df057a91d7047738c-filelists.sqlite.bz2 upload: pkg/hogehoge-0.0.1.rpm to s3://takipone-repotest/7/hogehoge-0.0.1.rpm upload: pkg/repodata/640c555807796f5b6b10a04a001ee48a7cc17cfdaf5496c7f710e1ecb33364cf-filelists.xml.gz to s3://takipone-repotest/7/repodata/640c555807796f5b6b10a04a001ee48a7cc17cfdaf5496c7f710e1ecb33364cf-filelists.xml.gz upload: pkg/repodata/95753241725d3d8dd859d45447001cbc03b4988ac5c86e0bd85acd2391f87495-primary.xml.gz to s3://takipone-repotest/7/repodata/95753241725d3d8dd859d45447001cbc03b4988ac5c86e0bd85acd2391f87495-primary.xml.gz $
これでOKです!
CloudFrontの設定
設定したS3バケットをオリジンとするCloudFrontディストリビューションを作成します。一般的なディストリビューション作成と特に変わりませんが、HTTPリダイレクトを動作させるために[Origin Domain Name]にはオートコンプリートの候補に出てくる通常のS3バケットのURLではなく、Static Website HostingのURL((バケット名).s3-website-(リージョン名).amazonaws.com)を指定することに注意しましょう。
これでOKです! *3
動作確認
では、先ほどのYumリポジトリの設定ファイルにあるリポジトリURLをCloudFrontに変更し、yumコマンドを実行してみます。
/etc/yum.repos.d/hoge.repo
[hoge] baseurl=http://XXXXXXXXXXXXX.cloudfront.net/$releasever/ enable=yes gogpcheck=no
Amazon Linuxの既定では、/etc/yum.confの以下の設定によって$releaseverは「latest」になります。
/etc/yum.conf
# by default the yum configuration will point to the latest release # of Amazon Linux AMI. If you prefer not to automatically move to # new releases, comment out this line. releasever=latest
CloudFront→S3に来たところで、リダイレクトルールによって/latestのアクセスは/7にリダイレクト、今回配置したリポジトリが参照できるはずです。
$ sudo yum clean all 読み込んだプラグイン:priorities, update-motd, upgrade-helper リポジトリー 'hoge' は構成中に名前がありませんので ID を使います リポジトリーを清掃しています: amzn-main amzn-updates hoge Cleaning up everything $ sudo yum info hogehoge 読み込んだプラグイン:priorities, update-motd, upgrade-helper リポジトリー 'hoge' は構成中に名前がありませんので ID を使います amzn-main/latest | 2.1 kB 00:00 amzn-main/latest/group | 35 kB 00:00 amzn-main/latest/primary_db | 3.3 MB 00:00 amzn-updates/latest | 2.3 kB 00:00 amzn-updates/latest/group | 35 kB 00:00 amzn-updates/latest/updateinfo | 218 kB 00:00 amzn-updates/latest/primary_db | 81 kB 00:00 hoge/latest | 2.9 kB 00:00 hoge/latest/primary_db | 1.6 kB 00:00 利用可能なパッケージ 名前 : hogehoge アーキテクチャー : x86_64 バージョン : 0.0.1 リリース : 1 容量 : 1.8 k リポジトリー : hoge/latest 要約 : no description given URL : http://example.com/no-uri-given ライセンス : unknown 説明 : no description given $
CloudFront経由でパッケージ情報が取得できました!
まとめ
YumリポジトリをS3とCloudFrontで配信する構成と、S3のリダイレクト設定についてご紹介しました。実際の運用にはリポジトリメタデータをパッケージ更新に合わせて更新する必要があるため、メタデータのHTTPヘッダを変更してキャッシュ保持期間を短めに設定するなどのチューニングが推奨されます。以下の記事が参考になると思います。(みんな悩んでるんですねぇw)
- CloudFrontのキャッシュ時間(TTL)はどの程度なのか | Developers.IO
- S3バケットに含まれる全オブジェクトのCache-Controlを書き換える、一撃で! | Developers.IO
- Amazon S3の画像をAWS Cloudfrontで配信するキャッシュコントロールをAWS Lambdaで自動化する | Developers.IO
- [S3, CloudFront] アップロード済みファイルのメタ情報を一括で変更する | Developers.IO
参考URL
- rpmの作り方(rpmbuild/checkinstall/fpm)とrpmレポジトリの作り方 - Qiita
- 6.3.2. [repository] オプションの設定 | Red Hat Enterprise Linux 6 導入ガイド
- 6.3.3. Yum 変数の使用 | Red Hat Enterprise Linux 6 導入ガイド
- Configure a Bucket for Website Hosting - Amazon Simple Storage Service